﻿#include "anchoritem.h"
#include <QDebug>
#include <QtMath>
#include <QVector3D>

AnchorItem::AnchorItem(QRectF rect, QPixmap map)
{
	m_ItemPixmap = map;
	m_ItemSize = QSizeF(rect.width(), rect.height());
	m_CurrentScenePos = rect.topLeft();
	m_ItemRatio = m_ItemSize.width() / m_ItemSize.height();
	m_TopRightAngle = qAtan(m_ItemRatio);
	//    qDebug()<<qRadiansToDegrees(m_TopRightAngle);

	m_TopLeftAngle = M_PI - m_TopRightAngle;
	//    qDebug()<<qRadiansToDegrees(m_TopLeftAngle);

	m_BottomRightAngle = -1.0 * m_TopRightAngle;
	//    qDebug()<<qRadiansToDegrees(m_BottomRightAngle);

	m_BottomLeftAngle = -1.0 * m_TopLeftAngle;
	//    qDebug()<<qRadiansToDegrees(m_BottomLeftAngle);

	setFlag(QGraphicsItem::ItemIsFocusable);
	setFlag(QGraphicsItem::ItemIsSelectable);
	setAcceptHoverEvents(true);

	InitPixmap();
	ItemResize();
	setPos(m_CurrentScenePos);
}

QRectF AnchorItem::boundingRect() const
{
	QRectF rect = getItemRect();
	if (isSelected())
	{
		rect.adjust(-m_Internal, -m_Internal, m_Internal, m_Internal);
		rect.adjust(-m_EllipseWidth, -m_EllipseWidth, m_EllipseWidth, m_EllipseWidth);
		rect.adjust(0, 0, 0, m_LineLen + m_RotateEllipseWidth);
	}
	return  rect;
}

void AnchorItem::paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget)
{
	painter->setRenderHint(QPainter::Antialiasing, true);
	painter->setRenderHint(QPainter::SmoothPixmapTransform, true);

	painter->setPen(Qt::NoPen);
	painter->setBrush(Qt::NoBrush);

	painter->drawPixmap(getItemRect(), m_ItemPixmap, m_ItemPixmap.rect());

	if (isSelected())
	{
		QRectF rect = getItemRect();
		const qreal penWidth = 0;
		// 边框区域颜色
		QColor color = QColor(Qt::gray);
		// 绘制四周边框虚线
		painter->setPen(QPen(color, penWidth, Qt::DashLine));
		painter->setBrush(Qt::NoBrush);

		rect.adjust(-m_Internal, -m_Internal, m_Internal, m_Internal);
		painter->drawRect(rect);

		// 绘制到旋转框的虚线
		const qreal roatePointStartX = rect.left() + rect.width() / 2;
		const qreal roatePointStartY = rect.bottom();
		const qreal roatePointEndX = rect.left() + rect.width() / 2;
		const qreal roatePointEndY = rect.bottom() + m_LineLen;
		painter->drawLine(QLineF(QPointF(roatePointStartX, roatePointStartY),
			QPointF(roatePointEndX, roatePointEndY)));

		// 绘制控制点
		painter->setPen(Qt::NoPen);
		//top-left
		painter->drawPixmap(m_TopLeftRect, m_ScalePixmap, m_ScalePixmap.rect());
		//bottom-left
		painter->drawPixmap(m_BottomLeftRect, m_ScalePixmap, m_ScalePixmap.rect());
		//top-right
		painter->drawPixmap(m_TopRightRect, m_ScalePixmap, m_ScalePixmap.rect());
		//bottom-left
		painter->drawPixmap(m_BottomRightRect, m_ScalePixmap, m_ScalePixmap.rect());
		// rotate
		painter->drawPixmap(m_RotateRect, m_RotatePixmap, m_RotatePixmap.rect());
	}
}

void AnchorItem::keyPressEvent(QKeyEvent* event)
{
	QGraphicsItem::keyPressEvent(event);
}

void AnchorItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
	setFocus();
	if (m_CursorShape == HAND_OPEN_CURSOR)
	{
		m_PressScenePos = event->scenePos();
		m_CursorShape = HAND_CLOSE_CURSOR;
		setCursor(Qt::ClosedHandCursor);
		m_Operation = ITEM_MOVE;
	}
	else if ((m_CursorShape == RESIZE_TOPLEFT_CURSOR) ||
		(m_CursorShape == RESIZE_TOPRIGHT_CURSOR) ||
		(m_CursorShape == RESIZE_BOTTOMLEFT_CURSOR) ||
		(m_CursorShape == RESIZE_BOTTOMRIGHT_CURSOR))
	{
		m_PressItemPos = event->pos();
		m_Operation = ITEM_RESIZE;
	}
	else if (m_CursorShape == ROTATE_CURSOR)
	{
		m_PressItemPos = event->pos();
		m_Transform = transform();
		m_Operation = ITEM_ROTATE;
		setCursor(m_RotatePressCursor);
	}
	QGraphicsItem::mousePressEvent(event);
}

void AnchorItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
{
	switch (m_Operation) {
	case ITEM_MOVE:
	{
		setPos(m_CurrentScenePos + event->scenePos() - m_PressScenePos);
		emit itemPos(m_CurrentScenePos + event->scenePos() - m_PressScenePos);
		update();
	}
	break;
	case ITEM_RESIZE:
	{
		QPointF diff = event->pos() - m_PressItemPos;
		m_PressItemPos = event->pos();
		qreal width, height;

		// 如果diff的宽大于高，则计算宽，在根据比例计算高
		if (abs(diff.x()) >= abs(diff.y()))
		{
			switch (m_CursorShape) {
			case RESIZE_TOPLEFT_CURSOR:
			{
				width = m_ItemSize.width() - 2 * diff.x();
				height = width / m_ItemRatio;
			}
			break;
			case RESIZE_TOPRIGHT_CURSOR:
			{
				width = m_ItemSize.width() + 2 * diff.x();
				height = width / m_ItemRatio;
			}
			break;
			case RESIZE_BOTTOMLEFT_CURSOR:
			{
				width = m_ItemSize.width() - 2 * diff.x();
				height = width / m_ItemRatio;
			}
			break;
			case RESIZE_BOTTOMRIGHT_CURSOR:
			{
				width = m_ItemSize.width() + 2 * diff.x();
				height = width / m_ItemRatio;
			}
			break;
			default:
			{
				width = m_ItemSize.width();
				height = m_ItemSize.height();
			}
			break;
			}
		}
		else {
			// 如果diff的高大于宽，则计算高，在根据比例计算宽
			switch (m_CursorShape) {
			case RESIZE_TOPLEFT_CURSOR:
			{
				height = m_ItemSize.height() - 2 * diff.y();
				width = height * m_ItemRatio;
			}
			break;
			case RESIZE_TOPRIGHT_CURSOR:
			{
				height = m_ItemSize.height() - 2 * diff.y();
				width = height * m_ItemRatio;
			}
			break;
			case RESIZE_BOTTOMLEFT_CURSOR:
			{
				height = m_ItemSize.height() + 2 * diff.y();
				width = height * m_ItemRatio;
			}
			break;
			case RESIZE_BOTTOMRIGHT_CURSOR:
			{
				height = m_ItemSize.height() + 2 * diff.y();
				width = height * m_ItemRatio;
			}
			break;
			default:
			{
				width = m_ItemSize.width();
				height = m_ItemSize.height();
			}
			break;
			}
		}

		// 限制宽度范围
		if (width < 50)
		{
			width = 50;
			height = width / m_ItemRatio;
		}
		else if (width > 500)
		{
			width = 500;
			height = width / m_ItemRatio;
		}

		m_ItemSize = QSizeF(width, height);
		ItemResize();
		update();
	}
	break;
	case ITEM_ROTATE:
	{
		QVector2D startVect = QVector2D(m_PressItemPos);
		startVect.normalize();
		QVector2D endVect = QVector2D(event->pos());
		endVect.normalize();

		qreal value = QVector2D::dotProduct(startVect, endVect);
		if (value > 1.0)
			value = 1.0;
		else if (value < -1.0)
			value = -1.0;

		qreal angle = qRadiansToDegrees(qAcos(value));

		QVector3D vect = QVector3D::crossProduct(QVector3D(startVect, 1.0), QVector3D(endVect, 1.0));
		if (vect.z() < 0)
			angle *= -1.0;

		m_Transform.rotate(angle);
		setTransform(m_Transform);
		update();
	}
	break;
	default:break;
	}
	QGraphicsItem::mouseMoveEvent(event);
}

void AnchorItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
{
	clearFocus();
	setCursor(Qt::ArrowCursor);
	m_CursorShape = ARROR_CURSOR;
	m_Operation = ITEM_NONE;
	m_CurrentScenePos = pos();
	QGraphicsItem::mouseReleaseEvent(event);
}

void AnchorItem::hoverEnterEvent(QGraphicsSceneHoverEvent* event)
{
	if (!isSelected())
	{
		m_CursorShape = HAND_OPEN_CURSOR;
		setCursor(Qt::OpenHandCursor);
	}
	else {
		QPointF pos = event->pos();
		QRectF rect = getItemRect();
		qreal angle = qAtan2(transform().m12(), transform().m11());
		QMarginsF pad = QMarginsF(1, 1, 1, 1);
		rect.adjust(-m_Internal, -m_Internal, m_Internal, m_Internal);
		if ((m_TopLeftRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_TOPLEFT_CURSOR;
			angle = m_TopLeftAngle - angle;
			setCursor(GetResizeCursorShape(angle));
			setToolTip(QString("缩放"));
		}
		else if ((m_BottomRightRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_BOTTOMRIGHT_CURSOR;
			angle = m_BottomRightAngle - angle;
			setCursor(GetResizeCursorShape(angle));
			setToolTip(QString("缩放"));
		}
		else if ((m_TopRightRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_TOPRIGHT_CURSOR;
			angle = m_TopRightAngle - angle;
			setCursor(GetResizeCursorShape(angle));
			setToolTip(QString("缩放"));
		}
		else if ((m_BottomLeftRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_BOTTOMLEFT_CURSOR;
			angle = m_BottomLeftAngle - angle;
			setCursor(GetResizeCursorShape(angle));
			setToolTip(QString("缩放"));
		}
		else if ((m_RotateRect + pad).contains(pos))
		{
			m_CursorShape = ROTATE_CURSOR;
			setCursor(m_RotateHoverCursor);
			setToolTip(QString("旋转"));
		}
		else {
			if (rect.contains(pos))
			{
				m_CursorShape = HAND_OPEN_CURSOR;
				setCursor(Qt::OpenHandCursor);
				setToolTip(QString("移动"));
			}
		}
	}
	QGraphicsItem::hoverEnterEvent(event);
}

void AnchorItem::hoverMoveEvent(QGraphicsSceneHoverEvent* event)
{
	if (!isSelected())
	{
		m_CursorShape = HAND_OPEN_CURSOR;
		setCursor(Qt::OpenHandCursor);
	}
	else {
		QPointF pos = event->pos();
		QRectF rect = getItemRect();
		qreal angle = qAtan2(transform().m12(), transform().m11());
		QMarginsF pad = QMarginsF(1, 1, 1, 1);
		rect.adjust(-m_Internal, -m_Internal, m_Internal, m_Internal);
		if ((m_TopLeftRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_TOPLEFT_CURSOR;
			angle = m_TopLeftAngle - angle;
			//            qDebug()<<qRadiansToDegrees(angle);
			setCursor(GetResizeCursorShape(angle));
		}
		else if ((m_BottomRightRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_BOTTOMRIGHT_CURSOR;
			angle = m_BottomRightAngle - angle;
			//            qDebug()<<qRadiansToDegrees(angle);
			setCursor(GetResizeCursorShape(angle));
		}
		else if ((m_TopRightRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_TOPRIGHT_CURSOR;
			angle = m_TopRightAngle - angle;
			//            qDebug()<<qRadiansToDegrees(angle);
			setCursor(GetResizeCursorShape(angle));
		}
		else if ((m_BottomLeftRect + pad).contains(pos))
		{
			m_CursorShape = RESIZE_BOTTOMLEFT_CURSOR;
			angle = m_BottomLeftAngle - angle;
			//            qDebug()<<qRadiansToDegrees(angle);
			setCursor(GetResizeCursorShape(angle));
		}
		else if ((m_RotateRect + pad).contains(pos))
		{
			//            qDebug()<<"rotate";
			m_CursorShape = ROTATE_CURSOR;
			setCursor(m_RotateHoverCursor);
		}
		else {
			if (rect.contains(pos))
			{
				m_CursorShape = HAND_OPEN_CURSOR;
				setCursor(Qt::OpenHandCursor);
			}
		}
	}
	QGraphicsItem::hoverMoveEvent(event);
}

void AnchorItem::hoverLeaveEvent(QGraphicsSceneHoverEvent* event)
{
	m_CursorShape = ARROR_CURSOR;
	setCursor(Qt::ArrowCursor);
	QGraphicsItem::hoverLeaveEvent(event);
}

void AnchorItem::contextMenuEvent(QGraphicsSceneContextMenuEvent* event)
{
	QGraphicsItem::contextMenuEvent(event);
}

QVariant AnchorItem::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant& value)
{
	if (change == QGraphicsItem::ItemSelectedChange)
		prepareGeometryChange();

	return QGraphicsItem::itemChange(change, value);
}

QRectF AnchorItem::getItemRect() const
{
	// 以图元的中心为原点
	return QRectF(-m_ItemSize.width() / 2, -m_ItemSize.height() / 2,
		m_ItemSize.width(), m_ItemSize.height());
}

void AnchorItem::InitPixmap()
{
	m_ScalePixmap = QPixmap(":/icons/circle_grey.png");
	m_RotatePixmap = QPixmap(":/icons/rotate.png");

	m_RotateHoverCursor = QCursor(QPixmap(":/icons/rotate_hover.png").scaled(32, 32, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
	m_RotatePressCursor = QCursor(QPixmap(":/icons/rotate_press.png").scaled(32, 32, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
}

void AnchorItem::ItemResize()
{
	QRectF rect = getItemRect();
	rect.adjust(-m_Internal, -m_Internal, m_Internal, m_Internal);
	m_TopLeftRect = QRectF(rect.x() - m_EllipseWidth / 2, rect.y() - m_EllipseWidth / 2, m_EllipseWidth, m_EllipseWidth);
	m_BottomLeftRect = QRectF(rect.x() - m_EllipseWidth / 2, rect.bottomLeft().y() - m_EllipseWidth / 2, m_EllipseWidth, m_EllipseWidth);
	m_TopRightRect = QRectF(rect.topRight().x() - m_EllipseWidth / 2, rect.y() - m_EllipseWidth / 2, m_EllipseWidth, m_EllipseWidth);
	m_BottomRightRect = QRectF(rect.bottomRight().x() - m_EllipseWidth / 2, rect.bottomRight().y() - m_EllipseWidth / 2, m_EllipseWidth, m_EllipseWidth);
	m_RotateRect = QRectF(rect.left() + rect.width() / 2 - m_RotateEllipseWidth / 2, rect.bottom() + m_LineLen, m_RotateEllipseWidth, m_RotateEllipseWidth);
}

Qt::CursorShape AnchorItem::GetResizeCursorShape(qreal angle)
{
	qreal sector = M_PI_4;
	qreal value = angle + sector / 2;

	qreal theta = fmod(value, M_PI);
	if (theta < 0)
	{
		theta += M_PI;
	}
	int index = static_cast<int>(floor(theta / sector));
	switch (index) {
	case 0: return Qt::SizeHorCursor;
	case 1: return Qt::SizeBDiagCursor;
	case 2: return Qt::SizeVerCursor;
	case 3: return Qt::SizeFDiagCursor;
	default: return Qt::ArrowCursor;
	}
}

